// 状态管理
/**
 * 步骤说明：
 * 1、导入模块 createStore，这里并不是直接使用new Vuex()，而是使用Vuex中的store类
 * 2、创建store实例，createStore({})
 * 3、导出store模块
 */

// 1、导入模块
import { createStore } from "vuex"
// 导入Mutations类型常量
import { INCREMENT } from "./mutations-type"

// 模块A
const moduleA = {
	state: {
		name: "张三",
	},
	mutations: {
		// 这个state就是当前模块的state
		updateName(state, payload) {
			state.name = payload
		},
	},
	getters: {
		getName(state) {
			return state.name
		},
		// 获得根状态管理中的变量
		getFullName(state, getters, rootState) {
			console.log(rootState)
			return getters.getName + rootState.counter
		},
	},
	actions: {
		// 异步更新名字
		asyncUpdateName(context, payload) {
			console.log(context)
			// 模拟异步操作
			setTimeout(() => {
				context.commit("updateName", payload)
			}, 1000)
		},
	},
}

// 模块B
const moduleB = {
	state: {},
	mutations: {},
	getters: {},
	actions: {},
}

// 2、创建实例
const store = createStore({
	state: {
		counter: 1000,
		// 定义一个对象数组
		students: [
			{ id: 110, name: "张三", age: 18 },
			{ id: 111, name: "里斯", age: 24 },
			{ id: 112, name: "汪尔", age: 30 },
			{ id: 113, name: "小明", age: 10 },
		],
		// 新定义一个对象，测试响应式数据
		info: {
			id: 115,
			name: "比尔",
			age: 65,
		},
	},
	mutations: {
		// 这里面定义方法

		// counter加1的方法，默认需要传入state参数
		[INCREMENT](state) {
			state.counter++
		},
		// counter减1的方法，同样默认传入state方法
		decrement(state) {
			state.counter--
		},
		// 自定义增加的大小，传入参数payload
		incrementCount(state, payload) {
			// state.counter += count
			// 使用特殊提交风格执行这个函数时，payload是一个对象
			console.log(payload)
			state.counter += payload.count
		},
		// 自定义添加一个学生
		incrementStudent(state, stu) {
			state.students.push(stu)
		},
		// 更新Info，测试响应式数据
		updateInfo(state) {
			// 更改信息
			// state.info.name = "乔布斯"
			// 添加一个地址信息，在旧版本中这方式不是响应式的，页面数据不会发生改变；Vue3.0之后是响应式的
			state.info["address"] = "时光里43号"

			// 响应式添加
			// vue2.x格式
			// Vue.set(target, key, value)
			// vue3.0中使用ES6的特性Proxy实现响应式，这里直接添加或者删除数组中的元素（或者对象属性）都是响应式的

			// 如果在这个函数里面有一个异步操作，则devtools是无跟踪这个异步操作的，通常异步操作会定义在actions里面
		},
	},
	// 存放异步操作
	actions: {
		// 方式一：执行回调函数，告知外部组件异步操作已经完成，不够优雅
		// 默认传入一个context上下文参数，这里context可以认为是store，同样也可以接收一个外部参数
		// asyncUpdateInfo(context, payload) {
		// 	// 异步操作
		// 	setTimeout(() => {
		//         console.log(payload)
		// 		// 这里context（也可以认为是store）通过commit提交的方式执行updateInfo函数
		// 		context.commit("updateInfo")
		//         console.log(payload.message)
		//         // 执行回调函数
		//         payload.success()
		// 	}, 2000)
		// },

		// 方式二：方式一虽然能够实现，但不够优雅，使用Pormise改写
		asyncUpdateInfo(context, payload) {
			// 返回一个Promise对象
			return new Promise((resolve, rejevt) => {
				// 异步操作
				setTimeout(() => {
					console.log(payload)
					// 这里context（也可以认为是store）通过commit提交的方式执行updateInfo函数
					context.commit("updateInfo")

					// 返回一个数据
					resolve("执行完毕，我来自Promise对象")
				}, 2000)
			})
		},
	},
	// 定义一些基本的操作
	getters: {
		getCounter(state) {
			return state.counter
		},
		// 获得counter的平方
		getPowerCounter(state) {
			return state.counter * state.counter
		},
		// 获得年龄大于10岁的学生
		getStudentAgeBeyond10(state) {
			return state.students.filter((s) => s.age > 10)
		},
		// 获得年龄大于10岁的学生的个数，这里需要传一个getters参数，然后调用getters中的函数
		getStudentAgeBeyond10Length(state, getters) {
			return getters.getStudentAgeBeyond10.length
		},
		// 获得大于自定义年龄的学生，这里不能直接传入一个自定义的参数
		getStudentBeyondAge(state) {
			// 返回一个函数，然后再调用这个函数
			return (age) => {
				return state.students.filter((s) => s.age > age)
			}
		},
		// 返回Info内容
		getInfo(state) {
			return state.info
		},
	},
	modules: {
		a: moduleA,
		b: moduleB,
	},
})

// 导出store模块
export default store
